package com.magicstone.common.Licence.service;

import java.security.*;

import javax.crypto.*;
import javax.crypto.spec.*;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class Encryptor {
	private final static Log logger = LogFactory.getLog(Encryptor.class);
	public static final String ALGORITHM_DES = "DES";
	public static final String ALGORITHM_MD5 = "MD5";
	public static final String ALGORITHM_THREEDES = "DESede";
	public static final String ALGORITHM_AES = "AES";
	public static final String ALGORITHM_BLOWFISH = "Blowfish";
	private static final String DES_KEY = "2986a11fa45b2ac7";
	private static final String IV = "316bea0b8034f12a";
	private String algorithm;
	private int blocksize;
	
	private static Encryptor me;
	
	private Encryptor(){
	}

	public static Encryptor getInstance(){
		if(null == me){
			me = new Encryptor();
		}
		
		return me;
	}
	/*
	 * Generate md5 digest.
	 */
	public static String digest(String plaintext){
		String result = null;
		if(null != plaintext){
			logger.debug(plaintext);
			byte[] btInput = plaintext.getBytes();
            MessageDigest mdInst;
			try {
				mdInst = MessageDigest.getInstance(ALGORITHM_MD5);
	            mdInst.update(btInput);
	            byte[] md = mdInst.digest();
	            result = Convertor.bytesToHexString(md);
			} catch (Exception e) {
				logger.error(e.getMessage());
			}
		}
		return result;
	}
	/**
	 * 解密
	 */
	public byte[] decrypt(byte[] ivAndCiphertext) throws InvalidKeyException,
			NoSuchAlgorithmException, NoSuchPaddingException,
			InvalidAlgorithmParameterException, IllegalBlockSizeException,
			BadPaddingException {
		byte[] iv = new byte[this.blocksize];
		byte[] c = new byte[ivAndCiphertext.length - this.blocksize];
		System.arraycopy(ivAndCiphertext, 0, iv, 0, this.blocksize);
		System.arraycopy(ivAndCiphertext, this.blocksize, c, 0,
				ivAndCiphertext.length - this.blocksize);
		IvParameterSpec ivSpec = new IvParameterSpec(iv);
		Cipher cipher = Cipher.getInstance(algorithm + "/CBC/PKCS5Padding");
		Key key = generateKey(Convertor.hexStringToBytes(DES_KEY));
		cipher.init(Cipher.DECRYPT_MODE, key, ivSpec);
		return cipher.doFinal(c);
	}

	/**
	 * 加密
	 */
	public byte[] encrypt(byte[] plaintext)
			throws InvalidKeyException, NoSuchAlgorithmException,
			NoSuchPaddingException, InvalidAlgorithmParameterException,
			IllegalBlockSizeException, BadPaddingException {
		byte[] iv = Convertor.hexStringToBytes(IV);
		IvParameterSpec ivSpec = new IvParameterSpec(iv);
		Cipher cipher = Cipher.getInstance(algorithm + "/CBC/PKCS5Padding");
		Key key = generateKey(Convertor.hexStringToBytes(DES_KEY));
		cipher.init(Cipher.ENCRYPT_MODE, key, ivSpec);
		this.blocksize = cipher.getBlockSize();
		byte[] c = cipher.doFinal(plaintext);
		byte[] ivAndCiphertext = new byte[c.length + this.blocksize];
		System.arraycopy(iv, 0, ivAndCiphertext, 0, this.blocksize);
		System.arraycopy(c, 0, ivAndCiphertext, this.blocksize, c.length);
		return ivAndCiphertext;
	}

	public Key generateKey(byte[] key){
		if (key == null) {// 随机生成密钥
			KeyGenerator keygen;
			try {
				keygen = KeyGenerator.getInstance(algorithm);
				SecureRandom random = new SecureRandom();
				keygen.init(random);
				return keygen.generateKey();
			} catch (NoSuchAlgorithmException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		} else {// 从一组固定的原始数据（也许是由口令或者随机键产生的）生成密钥
			Key secretKey = new SecretKeySpec(key, algorithm);
			logger.debug(Convertor.bytesToHexString(secretKey.getEncoded()));
			return secretKey;
		}
		return null;
	}

	public void setAlgorithm(String algorithm) {
		this.algorithm = algorithm;
	}
}